﻿#define _CRT_SECURE_NO_WARNINGS 1
#include<iostream>
#include<vector>
#include<algorithm>
using namespace std;

//struct Goods
//{
//	string _name; // 名字 
//	double _price; // 价格 
//	int _evaluate; // 评价 
//	// ...
//	Goods(const char* str, double price, int evaluate)
//		:_name(str)
//		, _price(price)
//		, _evaluate(evaluate)
//	{}
//};
//
//struct ComparePriceLess
//{
//	bool operator()(const Goods& gl, const Goods& gr)
//	{
//		return gl._price < gr._price;
//	}
//};
//
//struct ComparePriceGreater
//{
//	bool operator()(const Goods& gl, const Goods& gr)
//	{
//		return gl._price > gr._price;
//	}
//};
//
//int main()
//{
//	vector<Goods> v = { { "苹果", 2.1, 5 }, { "⾹蕉", 3, 4 }, { "橙⼦", 2.2, 3}, { "菠萝", 1.5, 4 } };
//
//	// 类似这样的场景，我们实现仿函数对象或者函数指针⽀持商品中 
//	// 不同项的⽐较，相对还是⽐较⿇烦的，那么这⾥ lambda 就很好⽤了 
//
//	// 返回值类型一般省略
//	sort(v.begin(), v.end(), ComparePriceLess());
//	sort(v.begin(), v.end(), ComparePriceGreater());
//
//	sort(v.begin(), v.end(), [](const Goods& g1, const Goods& g2) {return g1._price < g2._price; });
//
//	sort(v.begin(), v.end(), [](const Goods& g1, const Goods& g2) {return g1._price > g2._price; });
//
//	sort(v.begin(), v.end(), [](const Goods& g1, const Goods& g2) {return g1._evaluate < g2._evaluate; });
//
//	sort(v.begin(), v.end(), [](const Goods& g1, const Goods& g2) {return g1._evaluate > g2._evaluate; });
//
//	return 0;
//}

//int q = 10;// 未捕捉 可以直接在 lambda 中使用
//
//int main()
//{
//	int a = 0, b = 1, c = 2, d = 3;// 未捕捉 不能直接在 lambda 中使用
//	auto func1 = [](int x)
//		{
//			int c = q;
//			a++;
//			b++;
//			int ret = a + b + x;// x 可以直接使用
//			return ret;
//		}
//	cout << func1() << endl;
//
//	return 0;
//}

//int q = 10;// 未捕捉 可以直接在 lambda 中使用
//
//// 捕捉列表 必须为空，因为 全局变量 不⽤捕捉就可以⽤，没有可被捕捉的 变量 
//auto func1 = []()
//	{
//		q++;
//	};
//
//int main()
//{
//	// lambda 捕捉只会向上捕捉
//	int a = 0, b = 1, c = 2, d = 3;// 未捕捉 不能直接在 lambda 中使用
//
//	// 传值捕捉 和 传引⽤捕捉
//	auto func1 = [a, &b](int x)// 只能
//		{
//			int c = q;
//			// a++;// 传值捕捉不能修改（相当于用 const 修饰）
//			b++;// 会修改外面的 b
//			int ret = a + b + x;// x 可以直接使用
//			return ret;
//		};
//
//	// 隐式值捕捉 
//	// ⽤了哪些变量就捕捉哪些变量 
//	auto func2 = [=]
//		{
//			int ret = a + b + c;
//			return ret;
//		};
//
//	cout << func2() << endl;
//	cout << func1(1) << endl;
//
//	// 隐式引⽤捕捉 
//	// ⽤了哪些变量就捕捉哪些变量 
//	auto func3 = [&]
//		{
//			a++;
//			c++;
//			d++;
//		};
//
//	func3();
//	cout << a << " " << b << " " << c << " " << d << endl;
//
//	// 混合捕捉1 (除了 a,b 其余都是引用捕捉)
//	auto func4 = [&, a, b]
//		{
//			//a++;
//			//b++;
//			c++;
//			d++;
//			return a + b + c + d;
//		};
//	func4();
//	cout << a << " " << b << " " << c << " " << d << endl;
//
//	// 混合捕捉2 (除了 a,b 其余都是值捕捉)
//	auto func5 = [=, &a, &b]
//		{
//			a++;
//			b++;
//			/*c++;
//			d++;*/
//			return a + b + c + d;
//		};
//	func5();
//	cout << a << " " << b << " " << c << " " << d << endl;
//
//	// 局部的静态 和 全局 变量不能捕捉，也不需要捕捉 
//	static int m = 0;// 未捕捉 可以直接在 lambda 中使用
//
//	auto func6 = []
//		{
//			int ret = q + m;
//			return ret;
//		};
//
//	 // 传值捕捉 本质是⼀种拷⻉，并且被 const 修饰了 
//	 // mutable (可变的) 相当于去掉 const 属性，可以修改了 
//	 // 但是修改了不会影响外⾯被捕捉的值，因为是⼀种拷⻉ 
//	auto func7 = [=]()mutable
//		{
//			a++;
//			b++;
//			c++;
//			d++;
//			return a + b + c + d;
//		};
//	cout << func7() << endl;
//	cout << a << " " << b << " " << c << " " << d << endl;
//
//
//	return 0;
//}

// C++ 11 新增两个默认成员函数--移动构造 + 移动赋值

// 移动构造：
// 如果没有自己实现（移动构造+析构+拷贝构造+赋值重载） 才 默认生成移动构造
// 默认移动构造：
// 1. 内置类型：浅拷贝
// 2. 自定义类型：本身的移动构造，没有就用拷贝构造

// 移动赋值：
// 如果没有自己实现（移动赋值+析构+拷贝构造+赋值重载） 才 默认生成移动赋值
// 默认移动构造：
// 1. 内置类型：浅拷贝
// 2. 自定义类型：本身的移动赋值，没有就用拷贝赋值

// 移动构造也是构造函数，写了之后不会自动生成构造函数+拷贝构造
// 移动赋值也是赋值重载函数，写了之后不会自动生成拷贝赋值重载

// 包装器
// template <class Ret, class... Args>
// class function<Ret(Args...)>;
// function<返回值<参数>>

//#include<functional>
//
//// 函数
//int f(int a, int b)
//{
//	return a + b;
//}
//
//// 仿函数
//struct Functor
//{
//public:
//	int operator() (int a, int b)
//	{
//		return a + b;
//	}
//};
//
//class Plus
//{
//public:
//	Plus(int n = 10)
//		:_n(n)
//	{}
//
//	static int plusi(int a, int b)
//	{
//		return a + b;
//	}
//
//	double plusd(double a, double b)
//	{
//		return (a + b) * _n;
//	}
//private:
//	int _n;
//};
//
//int main()
//{
//	// 包装各种可调⽤对象 (对象构造)
//	function<int(int, int)> f1 = f;// 函数指针
//	function<int(int, int)> f2 = Functor();// 仿函数
//	function<int(int, int)> f3 = [](int a, int b) {return a + b; };// lambda
//
//	// 有包装器：
//	cout << f1(1, 1) << endl;
//	cout << f2(1, 1) << endl;
//	cout << f3(1, 1) << endl;
//
//	// 如果没有包装器：
//	cout << ([](int a, int b) {return a + b; })(1, 1) << endl;
//	cout << f(1, 1) << endl;
//	cout << Functor()(1, 1) << endl;
//
//	// 包装 静态 成员函数 
//	// 成员函数要 指定类域 并且前⾯加 & 才能获取地址 (静态可加可不加 &)
//	function<int(int, int)> f4 = &Plus::plusi;
//	// function<int(int, int)> f4 = Plus::plusi;// 可以
//
//	cout << f4(1, 1) << endl;
//
//	// 包装 普通 成员函数 
//	// 普通成员函数还有⼀个隐含的 this 指针参数，所以绑定时 传对象 或者 对象的指针 过去都可以 
//	// 成员函数要 指定类域 并且前⾯加 & 才能获取地址 （非静态必须加 &）
//	function<double(Plus*, double, double)> f5 = &Plus::plusd;
//	Plus pd;
//	cout << f5(&pd, 1.1, 1.1) << endl;
//
//	function<double(Plus, double, double)> f6 = &Plus::plusd;
//	cout << f6(pd, 1.1, 1.1) << endl;
//	cout << f6(Plus(), 1.1, 1.1) << endl;
//
//	function<double(Plus&, double, double)> f7 = &Plus::plusd;
//	cout << f7(pd, 1.1, 1.1) << endl;
//
//	function<double(Plus&&, double, double)> f8 = &Plus::plusd;
//	cout << f8(move(pd), 1.1, 1.1) << endl;
//	cout << f8(Plus(), 1.1, 1.1) << endl;
//
//
//	return 0;
//}

// bind
#include<functional>

using placeholders::_1;// 占位符
using placeholders::_2;
using placeholders::_3;

int Sub(int a, int b)
{
	return (a - b) * 10;
}

int SubX(int a, int b, int c)
{
	return (a - b - c) * 10;
}

class Plus
{
public:
	static int plusi(int a, int b)
	{
		return a + b;
	}

	double plusd(double a, double b)
	{
		return a + b;
	}
};

int main()
{
	auto sub1 = bind(Sub, _1, _2);
	//_1 代表第一个实参传过来的位置（占位符）
	//_2 代表第二个实参传过来的位置（占位符）
	cout << sub1(10, 5) << endl;// 10 - 5

	// bind 本质返回的⼀个 仿函数对象 
	// 调整参数顺序（不常⽤） 
	// _1代表第⼀个实参 
	// _2代表第⼆个实参 
	// ...
	auto sub2 = bind(Sub, _2, _1);
	cout << sub2(10, 5) << endl;// 5 - 10

	// 调整参数个数（常⽤） 
	auto sub3 = bind(Sub, 100, _1);
	cout << sub3(5) << endl;

	auto sub4 = bind(Sub, _1, 100);
	cout << sub4(5) << endl;

	// 分别绑死第 123 个参数 
	auto sub5 = bind(SubX, 100, _1, _2);
	cout << sub5(5, 1) << endl;// a = 100, b = 5, c = 1
	auto sub6 = bind(SubX, _1, 100, _2);
	cout << sub6(5, 1) << endl;// a = 5, b = 100, c = 1
	auto sub7 = bind(SubX, _1, _2, 100);
	cout << sub7(5, 1) << endl;// a = 5, b = 1, c = 100

	// 成员函数对象进⾏ 绑死，就不需要每次都传递了 
	function<double(Plus&&, double, double)> f6 = &Plus::plusd;
	Plus pd;
	cout << f6(move(pd), 1.1, 1.1) << endl;
	cout << f6(Plus(), 1.1, 1.1) << endl;

	// bind ⼀般⽤于，绑死⼀些固定参数 
	function<double(double, double)> f7 = bind(&Plus::plusd, Plus(), _1, _2);
	cout << f7(1.1, 1.1) << endl;

	// 计算复利的 lambda 
	auto func1 = [](double rate, double money, int year)->double {
		double ret = money;
		for (int i = 0; i < year; i++)
		{
			ret += ret * rate;
		}
		return ret - money;
		};

	// 绑死⼀些参数，实现出⽀持不同年华利率，不同⾦额和不同年份计算出复利的结算利息 
	function<double(double)> func3_1_5 = bind(func1, 0.015, _1, 3);
	function<double(double)> func5_1_5 = bind(func1, 0.015, _1, 5);
	function<double(double)> func10_2_5 = bind(func1, 0.025, _1, 10);
	function<double(double)> func20_3_5 = bind(func1, 0.035, _1, 30);
	cout << func3_1_5(1000000) << endl;
	cout << func5_1_5(1000000) << endl;
	cout << func10_2_5(1000000) << endl;
	cout << func20_3_5(1000000) << endl;
	return 0;
}